# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.

from odoo import api, fields, models, _

import datetime

import logging
_logger = logging.getLogger(__name__)

class CrSafetyQuestion(models.Model):
    _name = "cr.safety.question"
    _description = "cr.safety.question"

    date_month = fields.Date('date_month')
    date_month_name = fields.Char( 'date_month_name',  compute ='_compute_date_month')
    name = fields.Char()

    @api.depends('date_month')
    def _compute_date_month(self ):
        for rec in self:
            rec.date_month_name = datetime.datetime.strftime(rec.date_month, "%Y-%m")

    employee_id = fields.Many2one('hr.employee', 'employee_id'  )
    parent_id = fields.Many2one('hr.employee', 'parent_id',  help='科室主管干部')
    parent2_id = fields.Many2one('hr.employee', 'parent2_id',  help='车间主管干部'  )
    major_id = fields.Many2one('hr.department', 'major_id',  help='专业')
    dept_id = fields.Many2one('hr.department', 'dept_id', help='责任部门')
    workshop_id = fields.Many2one('hr.department', 'workshop_id',  help='车间')
    quantity = fields.Integer(default=0)

    card_type = fields.Selection([
        ('none', '不发牌'),
        ('1st', '白牌'),
        ('2nd', '黄牌'),
        ('3rd', '红牌'),
        ('4th', '事故苗子')], default='none')

    is_limit = fields.Boolean(default=False, help='是否触碰红线高压线')
    is_self = fields.Boolean(default=False, help='是否自查')

    @api.model
    def create(self,values):
        rec = super( CrSafetyQuestion, self).create(values)
        rec._update_report(rec.date_month)
        return rec


    def write(self, values):
        ret = super( CrSafetyQuestion, self).write(values)
        for rec in self:
            print('question write, ', rec.date_month)
            rec._update_report(rec.date_month)
        return ret

    def unlink(self):
        date_month = self.date_month
        ret = super( CrSafetyQuestion, self).unlink()
        self._update_report(date_month)
        return ret

    def _update_report(self, date_month):
        # print('123456789,date,', date_month)
        print('question _update_report, ', date_month)
        vals_list = self.get_report( date_month)
        report_obj = self.env['cr.safety.question.report']

        for vals in vals_list:
            search_vals = {
                'date_month':date_month,
                'department_id': vals.get('department_id'), 
            }

            report = report_obj.find_or_create(search_vals)
            report_obj = report_obj | report
            # print('123456789,date,read,', report.date_month)


            vals2 = vals.copy()
            # del vals2['date_month']
            # del vals2['department_id']
            report.write(vals2)

        print('question to , report_obj.update_rank', date_month)
        report_obj.update_rank( date_month)
        
        return True

    @api.model
    def get_report(self, date_month):
        majors = self.env['hr.department'].search([['type','=','major']])
        majors2 = self._get_report2(date_month, majors, 'major')
        workshops = self.env['hr.department'].search([['type','in',['workshop', 'station']]])
        workshops2 = self._get_report2(date_month, workshops, 'workshop')

        return majors2 + workshops2

    @api.model
    def _get_report2(self, date_month, departments, dept_type):
        depts = dict( (dept.id, {
            'date_month': date_month,
            'department_id': dept.id, 
            'qty_question': 0,
            'qty_card': 0,
            'qty_self': 0,

            } ) for dept in departments )


        questions = self.env['cr.safety.question'].search([['date_month','=',date_month]])
        # cards = questions.filtered(lambda q: q.card_type != 'none')
        # total = sum( questions.mapped('quantity') )
        # total_card = sum( cards.mapped('quantity') )

        for quest in questions:
            dept_id = None
            if dept_type == 'major':
                dept_id = quest.major_id
            else:
                dept_id = quest.workshop_id
            
            if not dept_id:
                continue

            dept = depts[dept_id.id]
            dept['qty_question'] += quest.quantity
            dept['qty_card'] += quest.card_type != 'none' and quest.quantity or 0
            dept['qty_self'] += quest.is_self and quest.quantity or 0

        # for dept in depts.values():
        #     dept['total_question'] = total
        #     dept['total_card'] = total_card

        #     dept['percent_question'] = total and dept['qty_question'] / total or 0
        #     dept['percent_card'] = total_card and dept['qty_card'] / total_card or 0
        #     dept['percent_self'] = total and dept['qty_self']  / total or 0

        res = list( depts.values() )

        return res



class CrSafetyQuestionReport(models.Model):

    _name = 'cr.safety.question.report'
    _description = 'cr.safety.question.report'

    date_month = fields.Date('date_month')
    date_month_name = fields.Char( 'date_month_name',  compute ='_compute_date_month')
    name = fields.Char()

    @api.depends('date_month')
    def _compute_date_month(self ):
        for rec in self:
            rec.date_month_name = datetime.datetime.strftime(rec.date_month, "%Y-%m")

    department_id = fields.Many2one('hr.department', 'department_id', help='车间或专业')
    department_type = fields.Selection('department_type', related='department_id.type', help='车间或专业', store=True)
    group2_id = fields.Many2one('cr.safety.hr.dept.group2', 'group2_id', related='department_id.group2_id', store=True )

    # qty_question = fields.Integer(default=0)
    # qty_card = fields.Integer(default=0)
    # qty_self = fields.Integer(default=0)

    qty_question_self = fields.Integer(default=0)
    qty_question_noself = fields.Integer(default=0)
    qty_card_self = fields.Integer(default=0)
    qty_card_noself = fields.Integer(default=0)

    total_question = fields.Integer(default=0)
    total_card = fields.Integer(default=0)

    percent_question = fields.Float(default=0, digits=(8, 2))
    percent_card = fields.Float(default=0, digits=(8, 2) )
    percent_self = fields.Float(default=0, digits=(8, 2) )

    rank_question = fields.Integer(default=0 )
    rank_card = fields.Integer(default=0 )
    rank_self = fields.Integer(default=0 )

    is_1st_rank_question = fields.Boolean(default=False )
    is_last_rank_question = fields.Boolean(default=False )
    is_1st_rank_card = fields.Boolean(default=False )
    is_last_rank_card = fields.Boolean(default=False )
    is_1st_rank_self = fields.Boolean(default=False )
    is_last_rank_self = fields.Boolean(default=False )

    @api.model
    def create(self,values):
        _logger.info(values)
        date_month = values.get('date_month')
        department_id = values.get('department_id')
        obj = self.search([
            ['date_month','=',date_month],
            ['department_id','=',department_id] ])


        if obj:
            obj.write(values)
            return obj


        # print('123456789,values', values)
        # values = self._get_new_values(values)
        # print('123456789,values 2', values)
        rec =  super(CrSafetyQuestionReport, self).create(values)
        return rec

    @api.model
    def create_many(self,values):
        rpts = []
        for value in values:
            rpts.append(self.create(value))
        return rpts

    def write(self,values):
        # values = self._get_new_values(values)
        ret =  super(CrSafetyQuestionReport, self).write(values)
        return ret

    def _get_new_values(self, values):
        vals = {
            'qty_question': values.get('qty_question_self', 0) + values.get('qty_question_noself', 0),
            'qty_card': values.get('qty_card_self', 0) + values.get('qty_card_noself', 0),
            'qty_self': values.get('qty_question_self', 0) + values.get('qty_card_self', 0),
        }

        vals.update( values )
        return vals



    @api.model
    def find_or_create(self,values):
        date_month = values.get('date_month')
        department_id = values.get('department_id')
        obj = self.search([
            ['date_month','=',date_month],
            ['department_id','=',department_id] ])

        if obj:

            return obj

        rec = self.create(values)
        return rec

    @api.model
    def update_rank(self,date_month):
        print('report , update_rank', date_month)
        def set_rank(date_month, group2_id, value_field, rank_field):
            obj = self.search([
                ['date_month','=',date_month],
                ['group2_id','=',group2_id] ], order=value_field )

            last_rank = 1
            last_value = 0
            for index, rec in enumerate(obj):
                value = getattr(rec, value_field)
                rank = value == last_value and last_rank or index + 1
                setattr(rec, rank_field, rank)
                last_rank = rank
                last_value = value

            # 计算是否组内第一, 是否组内倒数第一

            for rec in obj:
                rank = getattr(rec, rank_field)
                if rank == 1:
                    setattr(rec, 'is_1st_' + rank_field, True)
                elif rank == last_rank:
                    setattr(rec, 'is_last_' + rank_field, True)

        reports = self.search([['date_month','=',date_month]])
        total_question_noself = sum( reports.mapped('qty_question_noself') )
        total_question_self = sum( reports.mapped('qty_question_self') )

        total_card_noself = sum( reports.mapped('qty_card_noself') )
        total_card_self = sum( reports.mapped('qty_card_self') )

        total_question = total_question_noself + total_question_self
        total_card = total_card_noself + total_card_self

        for rpt in reports:
            percent_question = total_question and (rpt.qty_question_noself + rpt.qty_question_self ) / total_question or 0
            percent_card = total_card and (rpt.qty_card_noself + rpt.qty_card_self) / total_card or 0

            qty_noself = rpt.qty_question_noself + rpt.qty_card_noself
            print('report , update_rank 1 ', qty_noself, rpt.department_id.name)
            print('report , update_rank 2 ', rpt.qty_question_noself, rpt.qty_card_noself)
            percent_self = qty_noself and (rpt.qty_question_self + rpt.qty_card_self) / qty_noself  or 0
            print('report , update_rank 3 ', qty_noself,rpt.qty_question_self , rpt.qty_card_self)
            print('report , update_rank 4 ', percent_self)

            rpt.write({
                'total_question': total_question,
                'total_card':total_card,
                'percent_question': percent_question,
                'percent_card': percent_card,
                'percent_self': percent_self,
            })

        group2_ids = self.env['cr.safety.hr.dept.group2'].search([])

        for group2 in group2_ids:
            set_rank(date_month, group2.id, 'percent_question', 'rank_question' )
            set_rank(date_month, group2.id, 'percent_card', 'rank_card' )
            set_rank(date_month, group2.id, 'percent_self', 'rank_self' )


    # 月末结算时, 触发这个函数 , 确认 三率报表 到 预警 和 积分
    def action_done( self ):
        for rec in self:
            rec._update_score_input()
            rec._update_alert()

        return True

    # TBDCODE 三率更新积分,  积分输入类型
    def _update_score_input(self):
        obj = self.env['cr.safety.score.input']
        date_month = fields.Date.to_string(self.date_month)

        def dept_score_input(obj, input_type_id_ref):
                input_type_id = self.env['ir.model.data'].xmlid_to_res_id(
                    input_type_id_ref, True)

                obj2 = obj.create({
                    'parent_id': self.department_id.manager_id.id,
                    'date_month': date_month,
                    'input_type_id': input_type_id,
                })
                obj2.action_done()
                return  obj | obj2

        def no_dept_score_input(obj, input_type_id_ref):
                input_type_id = self.env['ir.model.data'].xmlid_to_res_id(
                    input_type_id_ref, True)

                obj2 = obj.create({
                    'department_id': self.department_id.id,
                    'date_month': date_month,
                    'input_type_id': input_type_id,
                })

                obj2.action_done()
                return  obj | obj2


        if self.department_id.type == 'dept':
            if self.is_1st_rank_self:
                # 科室干部自查占比率 排名第一
                input_type_id_ref = 'cr_safety.safety_score_input_type_1071'
                obj = dept_score_input(obj, input_type_id_ref)

            if self.is_last_rank_question:
                # 科室干部站查问题率 排名末席
                input_type_id_ref = 'cr_safety.safety_score_input_type_2061'
                obj = dept_score_input(obj, input_type_id_ref)

            if self.is_last_rank_card:
                # 科室干部车站考核率 排名末席
                input_type_id_ref = 'cr_safety.safety_score_input_type_2062'
                obj = dept_score_input(obj, input_type_id_ref)

        elif self.department_id.type in ['workshop', 'station']:
            if self.is_1st_rank_self:
                # 车间自查占比率 排名第一
                input_type_id_ref = 'cr_safety.safety_score_input_type_1081'
                obj = no_dept_score_input(obj, input_type_id_ref)

            if self.is_last_rank_question:
                # 车间站查问题率 排名末席
                input_type_id_ref = 'cr_safety.safety_score_input_type_2071'
                obj = no_dept_score_input(obj, input_type_id_ref)

            if self.is_last_rank_card:
                # 车间 车站考核率 排名末席
                input_type_id_ref = 'cr_safety.safety_score_input_type_2072'
                obj = no_dept_score_input(obj, input_type_id_ref)


        return obj

    def _update_alert(self):
        if not (self.is_last_rank_question and self.is_last_rank_card):
            return None

        # 科室在组内 三率排名末席. 科室主管 被预警
        alert_obj = self.env['cr.safety.alert']
        ret = alert_obj.find_or_create(self.date_month, self.department_id.manager_id.id, 'cr_safety.safety_alert_type_1002')
        return ret



class CrSafetyTriRatio(models.Model):

    _name = "cr.safety.triratio"
    _description = "cr.safety.triratio"

    # 三率数据是职工端进行计算, 计算到部门粒度
    # 三率指标 是部门到指标
    # 部门主管领导 的 三率指标 指的是 所在部门的三率指标

    name = fields.Char()
    employee_id = fields.Many2one('hr.employee', 'employee_id'  )
    employee_name = fields.Char( 'employee_name',  related ='employee_id.name')
    employee_barcode = fields.Char( 'employee_barcode',  related ='employee_id.barcode')
    date_month = fields.Date('date_month')
    date_month_name = fields.Char( 'date_month_name',  compute ='_compute_date_month')
    ratio1 = fields.Float('ratio1')
    ratio2 = fields.Float('ratio2')
    ratio3 = fields.Float('ratio3')
    ratio1_name = fields.Char('ratio1_name', compute ='_compute_ratio')
    ratio2_name = fields.Char('ratio2_name', compute ='_compute_ratio')
    ratio3_name = fields.Char('ratio3_name', compute ='_compute_ratio')
    ratio1_rank = fields.Integer(default=0)
    ratio2_rank = fields.Integer(default=0)
    ratio1_is_last = fields.Boolean(default=False)
    ratio2_is_last = fields.Boolean(default=False)

    
    @api.depends('date_month')
    def _compute_date_month(self ):
        for rec in self:
            rec.date_month_name = datetime.datetime.strftime(rec.date_month, "%Y-%m")

    @api.depends('ratio1', 'ratio2', 'ratio3')
    def _compute_ratio(self ):
        for rec in self:
            rec.ratio1_name =  "%.2f%%" % (rec.ratio1  * 100)  
            rec.ratio2_name =  "%.2f%%" % (rec.ratio2  * 100)  
            rec.ratio3_name =  "%.2f%%" % (rec.ratio3  * 100)  


    @api.model
    def create(self,values):
        rec = super( CrSafetyTriRatio, self).create(values)
        rec._update_alert()
        return rec

    def write(self, values):
        ret = super( CrSafetyTriRatio, self).write(values)
        for rec in self:
            rec._update_alert()
        return ret

    # TBDCODE 三率更新 预警
    def _update_alert(self):
        if not (self.ratio1_is_last and self.ratio2_is_last):
            return None

        # 职工端, 产生数据.  科室在组内 三率排名末席. 科室主管 被预警
        alert_obj = self.env['cr.safety.alert']
        ret = alert_obj.find_or_create(self.date_month, self.employee_id.id, 'cr_safety.safety_alert_type_1002')
        return ret




